package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/gookit/color"
	"github.com/labstack/gommon/log"
	"io/fs"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
)

func main() {
	var ModFileDir string
	var err error
	flag.StringVar(&ModFileDir, "m", "./", "mod dir")
	flag.Parse()

	ModFileDir, err = filepath.Abs(ModFileDir)
	if err != nil {
		panic(err)
	}
	//go get -u github.com/ugorji/go/codec@latest
	log.Debug(ModFileDir)
	var mode []string
	filepath.Walk(ModFileDir, func(path string, info fs.FileInfo, err error) error {
		if !info.IsDir() && filepath.Base(path) == "go.mod" {
			mode = append(mode, path)
		}
		return nil
	})
	fmt.Println(len(mode), mode)
	rex := `.+ v`
	compilefront := regexp.MustCompile(rex)
	var wg sync.WaitGroup
	for _, s := range mode {
		wg.Add(1)
		go run(&wg, compilefront, s)
	}
	wg.Wait()
}

func run(wg *sync.WaitGroup, compilefront *regexp.Regexp, modPath string) {
	defer wg.Done()
	file, err := os.OpenFile(modPath, os.O_RDWR, 777)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	set := make(map[string]any)
	fileScanner := bufio.NewScanner(file)
	fileScanner.Split(bufio.ScanLines)
	for fileScanner.Scan() {
		text := fileScanner.Text()
		if len(text) == 0 || strings.HasPrefix(text, "//") { // 空或有注释
			continue
		}
		text = strings.TrimSpace(text)
		right := strings.TrimRight(compilefront.FindString(text), " v")
		set[right] = nil
	}

	var wgx sync.WaitGroup
	for key := range set {
		wgx.Add(1)
		go func(wgx *sync.WaitGroup) {
			defer wgx.Done()
			cmd := exec.Command("go", "get", key)
			cmd.Dir = filepath.Dir(modPath)
			color.Greenln(cmd.String())
			out, err := cmd.CombinedOutput()
			if err != nil {
				log.Warn(err)
				return
			}
			color.Blueln(string(out))
		}(&wgx)
		wgx.Wait()
	}
	cmd := exec.Command("go", "mod", "tidy")
	cmd.Dir = filepath.Dir(modPath)
	out, err := cmd.CombinedOutput()
	if err != nil {
		log.Fatal(err)
		return
	}
	color.Blueln(string(out))
}
